import { useEffect, useRef, useState } from 'react'
import './VideoExportModal.scss'
import RemoveSvg from '@/svg/RemoveSvg'
import useStateRef from '@/hooks/useStateRef'
import imageLoadManager from '@/lib/imageLoadManager'
import { loadImageInfo } from '@/utils/loadVideo'
import { showLoading } from '@/utils/loading'
import useNumInput from '@/hooks/useNumInput'
import CustomCanvas from '@/component/CustomCanvas'
import { showToast } from '@/utils/toast'
import * as dialog from '@tauri-apps/plugin-dialog'
import { dateFormat } from '@/utils/common'
import { invoke } from '@tauri-apps/api/core'
import { BaseDirectory, mkdir, remove, writeFile } from '@tauri-apps/plugin-fs'
import { useI18n } from '@/i18n'
interface Props {
  show: boolean
  onHide: () => void
  frameList: FrameInfo[]
  allFrameList: FrameInfo[]
  fps: number
}

const imageFmtList = [
  {
    name: 'MP4',
    ext: 'mp4',
  },
  {
    name: 'WEBM',
    ext: 'webm',
  },
  {
    name: 'GIF',
    ext: 'gif',
  },
]

const VideoExportModal = ({
  show,
  onHide,
  frameList,
  allFrameList,
  fps,
}: Props) => {
  const { t } = useI18n()
  const canvasRef = useRef<HTMLCanvasElement>(null)
  const imageFrameList = useRef<HTMLImageElement[]>([])
  const canvasCtx = useRef<CanvasRenderingContext2D | null>(null)
  const [canvasSize, setCanvasSize, canvasSizeRef] = useStateRef({
    width: 200,
    height: 200,
  })
  const [selecVideoFmt, onChangeSelecVideoFmt] = useState(imageFmtList[0].name)
  const [editFps, onChangeEditFps, editFpsStr, onBlurEditFps] = useNumInput(
    fps,
    {
      min: 1,
      max: 200,
      int: true,
    }
  )
  useEffect(() => {
    const task = async () => {
      if (frameList.length != 0) {
        const info = await loadImageInfo(frameList[0].url)
        setCanvasSize({
          width: info.width,
          height: info.height,
        })
        canvasRef.current.width = info.width
        canvasRef.current.height = info.height
      } else {
        setCanvasSize({ width: 200, height: 200 })
        canvasRef.current.width = 200
        canvasRef.current.height = 200
      }
    }
    task()
  }, [frameList])
  useEffect(() => {
    if (!show) {
      return
    }
    let isEnd = false
    const task = async () => {
      imageFrameList.current = await imageLoadManager.loadImageList(frameList)
      //   if (!play) {
      //     return
      //   }
      // 帧时间
      const frameTime = 1000 / fps
      let frame = 0
      let nowframeTime = 0
      let lastTime = 0
      canvasCtx.current = canvasRef.current.getContext('2d')
      canvasCtx.current.imageSmoothingEnabled = false
      const anim = (nowTime: number) => {
        const deltaTime = nowTime - lastTime
        lastTime = nowTime
        nowframeTime += deltaTime
        const addFrame = Math.floor(nowframeTime / frameTime)
        nowframeTime = nowframeTime % frameTime
        draw(frame)
        frame += addFrame
        if (frameList.length == 0) isEnd = true
        while (frame >= frameList.length && frameList.length != 0) {
          frame -= frameList.length
        }
        if (isEnd) return
        requestAnimationFrame(anim)
      }
      requestAnimationFrame(anim)
    }
    task()
    return () => {
      isEnd = true
    }
  }, [show, frameList, canvasSize])

  const draw = (frame = 0) => {
    if (frame < 0 || frame >= imageFrameList.current.length) {
      return
    }
    const ctx = canvasCtx.current
    if (!ctx) return
    const w = canvasSizeRef.current.width
    const h = canvasSizeRef.current.height
    ctx.clearRect(0, 0, w, h)
    if (frameList.length == 0) {
      return
    }
    const imageW = imageFrameList.current[frame].naturalWidth
    const imageH = imageFrameList.current[frame].naturalHeight
    ctx.drawImage(
      imageFrameList.current[frame],
      0,
      0,
      imageW,
      imageH,
      0,
      0,
      w,
      h
    )
  }

  async function onSave(): Promise<void> {
    const hideloading = showLoading(t('exporting'))
    try {
      const fmt = imageFmtList.find((item) => item.name == selecVideoFmt)
      let outPath = null
      outPath = await dialog.save({
        canCreateDirectories: true,
        title: t('exportVideo'),
        defaultPath: dateFormat(new Date(), 'MM_dd_hh_mm_ss') + '.' + fmt?.ext,
        filters: [
          {
            name: fmt.name,
            extensions: [fmt.ext],
          },
        ],
      })
      if (!outPath) return
      const hideloading = showLoading()
      try {
        await remove('img_to_video/input', {
          recursive: true,
          baseDir: BaseDirectory.AppData,
        })
        await mkdir('img_to_video/input', {
          baseDir: BaseDirectory.AppData,
        })
        await Promise.all(
          frameList.map(async (item, index) => {
            const buf = await item.file.arrayBuffer()
            writeFile(`img_to_video/input/${index}.png`, new Uint8Array(buf), {
              append: false,
              baseDir: BaseDirectory.AppData,
            })
          })
        )
        await invoke('img_to_video', {
          buffers: [],
          fps: editFps,
          outPath,
        })
        showToast(`${t('exportSuccessful')}：${outPath}`)
      } finally {
        hideloading()
      }
      // showToast(t('exportSuccessful'))
    } catch (e) {
      console.error(e)
      showToast(t('exportFailed'))
    } finally {
      hideloading()
    }
  }
  useEffect(() => {
    onChangeEditFps(`${fps}`)
  }, [fps])

  return (
    <div className="VideoExportModal-component">
      <div className={`VideoExportModal ${show ? 'show' : ''}`}>
        <div className="top">
          <div className="title">
            <span>{t('exportVideo')}</span>
          </div>
          <ripple-button className="remove" onClick={onHide}>
            <RemoveSvg />
          </ripple-button>
        </div>
        <div className="center-box">
          <div className="canvas-view">
            <CustomCanvas className="canvas" ref={canvasRef}></CustomCanvas>
          </div>
          <div className="input-box">
            <div className="label">
              <label>{t('exportFormat')}</label>
            </div>
            <select
              className="select"
              value={selecVideoFmt}
              onChange={(e) => {
                onChangeSelecVideoFmt(e.target.value)
              }}>
              {imageFmtList.map((item) => {
                return (
                  <option key={item.name} value={item.name}>
                    {item.name}
                  </option>
                )
              })}
            </select>
          </div>
          <div className="input-box">
            <div className="label">
              <label>FPS</label>
            </div>
            <input
              onBlur={onBlurEditFps}
              type="number"
              onChange={(e) => {
                onChangeEditFps(e.target.value)
              }}
              min={1}
              max={200}
              className="input"
              value={editFpsStr}></input>
          </div>
        </div>
        <div
          style={{
            justifyContent: 'flex-end',
            display: 'flex',
            alignItems: 'center',
            gap: 10,
            marginTop: 12,
          }}>
          <ripple-button
            style={{
              background: 'var(--primary-color)',
              color: 'white',
              width: 130,
              padding: '8px 0',
            }}
            onClick={onSave}>
            {t('export')}
          </ripple-button>
        </div>
      </div>
      <div className={`mask ${show ? 'show' : ''}`} onClick={onHide}></div>
    </div>
  )
}

export default VideoExportModal
